package com.ta.internal.multipart.upload;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * This class uploads an image or video form a path to server
 * 
 * @author vinay
 * 
 */
public class UploaderTask {
    private static final String TAG = "MultiPartUploaderTask";
    public static String MSG_FILE_NOT_FOUND = "Fielpath is invalid or null, try again.";
    public static String MSG_CONNECTION_ERROR = "Error connecting remote server, try again.";
    /*
     * private Context mContext;
     * 
     * public UploaderTask(Context context) { mContext = context; }
     */
    private Thread uploadThread;
    private Charset mCharset;

    /**
     * uplaod the media file along with other params. other params may be null
     * in case not required.
     * 
     * @param uploadHandler
     * 
     * @param url
     *            -url of the web interface uploader file on server
     * @param imageOrimageOrVideoPath
     *            - absolute path of the image/video file
     * @param uploadparams
     *            -additional parameter to be saved with image on server. e.g.
     *            user_id, username, user_location
     * @param charset
     *            -charset String encode Charset default is "UTF-8"
     */
    public void uploadFile( HttpType httpType,Handler uploadHandler) {
    	this.httpType = httpType;
    	uploadFile(uploadHandler, null);
    }
    private DefaultHttpClient httpclient;
    private HttpPost httppost;
    private HttpPut httpPut;
    private CustomMultipartEntity reqEntity;
    private HttpResponse response;
    private HttpEntity resEntity;
    private HttpType httpType;
    private long totalSize;
    public void uploadFile(final Handler uploadHandler, final Charset charset) {
	if (charset == null) { 
	    mCharset = Charset.defaultCharset();
	}
	
	uploadThread = new Thread(new Runnable() {
	    public void run() {
	    	switch (httpType) {
			case HttpPost:
				post(uploadHandler);
				break;
			case HttpPut:
				put(uploadHandler);
				break;
			}
	    }
	});
	uploadThread.start();
    }
    private void post(final Handler uploadHandler){
		String res = "";
		try {
		    httpclient = new DefaultHttpClient();
		    httppost = new HttpPost(url);
		    reqEntity = new CustomMultipartEntity(
			    HttpMultipartMode.BROWSER_COMPATIBLE, null,
			    mCharset,
			    new CustomMultipartEntity.ProgressListener() {

				@Override
				public void transferred(long num) {
				    // TODO Auto-generated method stub
				    Log.e("totalSize", "sizechange="+totalSize);

				    Message msg = new Message();
				    msg.what = 0;
				    msg.arg1 = (int) ((num / (float) totalSize) * 100);
				    uploadHandler.sendMessage(msg);
				}
			    });

		    if (fileparams != null)
			reqEntity = addFileParams(reqEntity);
		    if (uploadparams != null)
			reqEntity = addMoreParams(reqEntity, mCharset);
		    totalSize = reqEntity.getContentLength();
		    httppost.setEntity(reqEntity);
		    response = httpclient.execute(httppost);
		    resEntity = response.getEntity();
		    if (resEntity != null) {
			res = EntityUtils.toString(resEntity);
			System.out.println(res);
		    } // end if
		    if (resEntity != null) {
			resEntity.consumeContent();
		    } // end if
		    httpclient.getConnectionManager().shutdown();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", "Upload successful.");

		    if (response.getStatusLine().getStatusCode() / 100 == 2)
			msg.what = 1;
		    else
			msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (UnsupportedEncodingException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", MSG_CONNECTION_ERROR + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (ClientProtocolException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", MSG_CONNECTION_ERROR + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (FileNotFoundException e) {
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", "FileNotFoundException");
		    // b.putString("path", getPath());
		    b.putString("message", MSG_FILE_NOT_FOUND + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (IOException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", "IOException");
		    // b.putString("path", getPath());
		    b.putString("message", MSG_FILE_NOT_FOUND + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		}
	}
    private void put(final Handler uploadHandler){
		String res = "";
		try {
		    httpclient = new DefaultHttpClient();
		    httpPut = new HttpPut(url);

		    reqEntity = new CustomMultipartEntity(
			    HttpMultipartMode.BROWSER_COMPATIBLE, null,
			    mCharset,
			    new CustomMultipartEntity.ProgressListener() {

				@Override
				public void transferred(long num) {
				    // TODO Auto-generated method stub
				    Log.e("aaaa", "sizechange");
				  
				    Message msg = new Message();
				    msg.what = 0;
				    msg.arg1 = (int) ((num / (float) totalSize) * 100);
				    uploadHandler.sendMessage(msg);
				}
			    });

		    if (fileparams != null)
			reqEntity = addFileParams(reqEntity);
		    if (uploadparams != null)
			reqEntity = addMoreParams(reqEntity, mCharset);
		    totalSize = reqEntity.getContentLength();
		    httpPut.setEntity(reqEntity);
		    response = httpclient.execute(httpPut);
		    Log.e(TAG, response.getStatusLine().getStatusCode()+"---------------------result------code");
		    resEntity = response.getEntity();
		    if (resEntity != null) {
			res = EntityUtils.toString(resEntity);
			System.out.println(res);
		    } // end if
		    if (resEntity != null) {
			resEntity.consumeContent();
		    } // end if
		    httpclient.getConnectionManager().shutdown();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", "Upload successful.");

		    if (response.getStatusLine().getStatusCode() / 100 == 2)
			msg.what = 1;
		    else
			msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (UnsupportedEncodingException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", MSG_CONNECTION_ERROR + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (ClientProtocolException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", res);
		    // b.putString("path", getPath());
		    b.putString("message", MSG_CONNECTION_ERROR + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (FileNotFoundException e) {
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", "FileNotFoundException");
		    // b.putString("path", getPath());
		    b.putString("message", MSG_FILE_NOT_FOUND + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		} catch (IOException e) {
		    e.printStackTrace();
		    Message msg = Message.obtain();
		    // msg.obj = res;
		    Bundle b = new Bundle();
		    b.putString("result", "IOException");
		    // b.putString("path", getPath());
		    b.putString("message", MSG_FILE_NOT_FOUND + "");
		    msg.what = -1;
		    msg.setData(b);
		    uploadHandler.sendMessage(msg);
		}
	}
    /**
     * Add additional params to upload request; <br/>
     * such as user_id, username, reference_id for the user who's uploading this
     * image.
     * 
     * @param reqEntity
     * @param moreparams
     * @return
     * @throws UnsupportedEncodingException
     */
    private CustomMultipartEntity addMoreParams(
	    CustomMultipartEntity reqEntity, Charset charset)
	    throws UnsupportedEncodingException {
	for (int i = 0; i < uploadparams.size(); i++) {
	    reqEntity
		    .addPart(uploadparams.get(i).getParamKey(), new StringBody(
			    uploadparams.get(i).getParamValue(), charset));
	}

	return reqEntity;
    }

    /**
     * Add file params to the request entity
     * 
     * @param reqEntity
     * @param fileparams
     * @return
     * @throws UnsupportedEncodingException
     */
    private CustomMultipartEntity addFileParams(CustomMultipartEntity reqEntity)
	    throws UnsupportedEncodingException {

	for (UploadParams file : fileparams) {
	    Log.d(TAG + " " + file.getParamKey(), file.getParamValue());

	    FileBody filebodyVideo = new FileBody(
		    new File(file.getParamValue()));

	    reqEntity.addPart(file.getParamKey(), filebodyVideo);

	}

	return reqEntity;
    }

    public void closeConnect(){
//	httpclient.getConnectionManager().shutdown();
	switch (httpType) {
	case HttpPost:
		httppost.abort();
		break;
	case HttpPut:
		httpPut.abort();
		break;
	}
    }
    
    
    private String url;
    private List<UploadParams> uploadparams;
    private List<UploadParams> fileparams;
    public void setUploadParams(List<UploadParams> fileparams,
	    List<UploadParams> moreparams) {
	this.uploadparams = moreparams;
	this.fileparams = fileparams;
    }

    public void setUrl(String url) {
	this.url = url;
    }

}
